use crate::entity::sys_login_log::Entity as SysLoginLog;
use crate::entity::{sys_dept, sys_login_log, sys_operate_log, sys_user};
use chrono::NaiveDateTime;
use sea_orm::{
    ColumnTrait, DbConn, DbErr, DerivePartialModel, EntityTrait, FromQueryResult, PaginatorTrait,
    PartialModelTrait, QueryFilter, QueryOrder, QuerySelect, QueryTrait, Related,
};
use serde::Serialize;

#[derive(Debug, DerivePartialModel, FromQueryResult, Serialize)]
#[sea_orm(entity = "SysLoginLog")]
pub struct LoginLogVo {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub username: String,
    pub result: i8,
    pub user_ip: String,
    pub user_agent: String,
    pub created_at: NaiveDateTime,
}

#[derive(Debug, FromQueryResult, Serialize, Clone)]
pub struct OperateLogVo {
    pub id: i32,
    pub result: i8,
    pub request_method: String,
    pub request_path: String,
    pub request_query: Option<String>,
    pub request_data: Option<String>,
    pub operator_name: Option<String>,
    pub created_at: NaiveDateTime,
}

pub struct SysLog;

#[allow(unused)]
impl SysLog {
    ane_macros::model_list! {
        #model=sys_login_log
        #filter=[]
        #order=[Id:Desc]
        /// 分页列出登陆日志[sys_login_log]
        /// - username 可选, 查找包含的名字
        /// - result 可选, 查找结果
        pub fn list_login(Username.contains(username:Option<String>), Result.eq(result:Option<i8>))
    }

    /// 删除[sys_login_log], 当id不存在时, 抛出错误
    pub async fn del_login_log(db: &DbConn, id: i32) -> Result<bool, DbErr> {
        sys_login_log::Entity::delete_by_id(id)
            .exec(db)
            .await
            .map(|r| r.rows_affected > 0)
    }

    /// 分页列出[sys_operate_log]
    pub async fn list_operate(
        db: &DbConn,
        page: u64,
        page_size: u64,
        result: Option<i8>,
        cond: Option<sea_orm::sea_query::Cond>,
    ) -> Result<(u64, Vec<OperateLogVo>), DbErr> {
        let mut sql = sys_operate_log::Entity::find()
            .order_by_desc(sys_operate_log::Column::Id)
            .join_rev(
                sea_orm::JoinType::LeftJoin,
                sys_user::Entity::belongs_to(sys_operate_log::Entity)
                    .from(sys_user::Column::UserId)
                    .to(sys_operate_log::Column::OperatorId)
                    .into(),
            )
            .join_rev(
                sea_orm::JoinType::LeftJoin,
                <sys_dept::Entity as Related<sys_user::Entity>>::to(),
            )
            .column_as(sys_user::Column::Username, "operator_name")
            .apply_if(result, |sql, result| {
                sql.filter(sys_operate_log::Column::Result.eq(result))
            })
            .apply_if(cond, |sql, cond| sql.filter(cond))
            .into_model::<OperateLogVo>()
            .paginate(db, page_size);
        let total = sql.num_items().await?;
        let datas = sql.fetch_page(page).await?;
        Ok((total, datas))
    }

    /// 分页列出[sys_operate_log]
    pub async fn get_operate_by_id(
        db: &DbConn,
        id: i32,
        cond: Option<sea_orm::sea_query::Cond>,
    ) -> Result<Option<sys_operate_log::Model>, DbErr> {
        sys_operate_log::Entity::find_by_id(id)
            .order_by_desc(sys_operate_log::Column::Id)
            .join_rev(
                sea_orm::JoinType::LeftJoin,
                sys_user::Entity::belongs_to(sys_operate_log::Entity)
                    .from(sys_user::Column::UserId)
                    .to(sys_operate_log::Column::OperatorId)
                    .into(),
            )
            .join_rev(
                sea_orm::JoinType::LeftJoin,
                <sys_dept::Entity as Related<sys_user::Entity>>::to(),
            )
            .apply_if(cond, |sql, cond| sql.filter(cond))
            .one(db)
            .await
    }

    /// 删除[sys_operate_log]
    pub async fn del_operate_log(db: &DbConn, id: i32) -> Result<bool, DbErr> {
        sys_operate_log::Entity::delete_by_id(id)
            .exec(db)
            .await
            .map(|r| r.rows_affected > 0)
    }
}
